﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Demo.Core.CommonFunction;
using Demo.Identity.Permissions.Dto;
using Demo.Identity.Permissions.Entities;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Identity;
using Demo.Core.CommonExtension;

namespace Demo.Identity.Permissions
{
    /// <summary>
    /// 权限管理应用服务
    /// </summary>
    public class SysPermissionAppService : IdentityAppService, ISysPermissionAppService
    {
        #region 初始化

        private readonly IRepository<RolePermissions> _rolePermissionsRepository;
        private readonly IRepository<SysPermission> _sysPermissionsRepository;
        private readonly IRepository<IdentityUserRole> _userRolesRepository;

        public SysPermissionAppService(
            IRepository<RolePermissions> rolePermissionsRepository,
            IRepository<SysPermission> sysPermissionsRepository,
            IRepository<IdentityUserRole> userRolesRepository
        )
        {
            _rolePermissionsRepository = rolePermissionsRepository;
            _sysPermissionsRepository = sysPermissionsRepository;
            _userRolesRepository = userRolesRepository;
        }

        #endregion
        
        #region 按服务注册权限

        /// <summary>
        /// 按服务注册权限
        /// </summary>
        /// <param name="serviceName">服务名称</param>
        /// <param name="permissions">权限列表</param>
        /// <returns></returns>
        public async Task<bool> RegistPermission(string serviceName, List<SysPermissionDto> permissions)
        {
            //根据服务名称查询现有权限
            var entities = await AsyncExecuter.ToListAsync( 
                (await _sysPermissionsRepository.GetQueryableAsync()).Where(c => c.ServiceName == serviceName)
            );
            var lst = ObjectMapper.Map<List<SysPermissionDto>, List<SysPermission>>(permissions);
            ListCompare.MutiCompare(lst, entities, x => x.Code, async (entity, isNew) =>
            {
                if (isNew)
                {
                    //新增
                    await _sysPermissionsRepository.InsertAsync(entity);
                }
                else
                {
                    //修改
                    var tmp = lst.FirstOrDefault(x => x.Code == entity.Code);
                    //调用权限判断方法,如果code和name相同就不进行添加
                    if (!entity.Equals(tmp)&&tmp!=null)
                    {
                        entity.SetId(tmp.Id);
                        await _sysPermissionsRepository.UpdateAsync(entity);
                    }
                }
            }, out var needRemove);
            foreach (var item in needRemove)
            {
                //删除多余项
                await _sysPermissionsRepository.DeleteAsync(item.Value);
            }
            return true;
        }

        #endregion

        #region 按服务获取权限

        /// <summary>
        ///     按服务获取权限
        /// </summary>
        /// <param name="serviceName">服务名称</param>
        /// <returns>查询结果</returns>
        public async Task<List<SysPermissionDto>> GetPermissions(string serviceName)
        {
            var query = (await _sysPermissionsRepository.GetQueryableAsync()).Where(x => x.ServiceName == serviceName);
            //使用AsyncExecuter进行异步查询
            var lst = await AsyncExecuter.ToListAsync(query);
            //映射实体类到dto
            return ObjectMapper.Map<List<SysPermission>, List<SysPermissionDto>>(lst);
        }

        #endregion

        #region 获取完整权限树

        /// <summary>
        /// 获取完整权限树
        /// </summary>
        /// <returns>查询结果</returns>
        public async Task<List<PermissionTreeDto>> GetPermissionTree()
        {
            var per = await _sysPermissionsRepository.ToListAsync();
            var lst = ObjectMapper.Map<List<SysPermission>, List<PermissionTreeDto>>(per);
            return PermissionTreeBuilder.Build(lst);
        }

        #endregion

        #region 获取用户权限码

        /// <summary>
        /// 获取用户权限码
        /// </summary>
        /// <param name="userId">用户编号</param>
        /// <returns>查询结果</returns>
        public async Task<List<string>> GetUserPermissionCode(Guid userId)
        {
            var query = from user in (await _userRolesRepository.GetQueryableAsync()).Where(c => c.UserId == userId)
                join rp in (await _rolePermissionsRepository.GetQueryableAsync()) on user.RoleId equals rp.RoleId
                join pe in (await _sysPermissionsRepository.GetQueryableAsync()) on rp.PermissionId equals pe.Id
                select pe.Code;
            var permission = await AsyncExecuter.ToListAsync(query);
            return permission.Distinct(x=>x);
        }

        #endregion
    }
}